/**
 * create by zhike
 * date:2015年3月12日
 */
package com.acooly.module.openapi.client.provider.wsbank.marshall;

import com.acooly.core.utils.Dates;
import com.acooly.core.utils.Ids;
import com.acooly.module.openapi.client.api.exception.ApiClientException;
import com.acooly.module.openapi.client.api.marshal.ApiUnmarshal;
import com.acooly.module.openapi.client.api.message.MessageFactory;
import com.acooly.module.openapi.client.provider.wsbank.WsbankConstants;
import com.acooly.module.openapi.client.provider.wsbank.domain.WsbankNotify;
import com.acooly.module.openapi.client.provider.wsbank.enums.WsbankServiceEnum;
import com.acooly.module.openapi.client.provider.wsbank.enums.WsbankSignTypeEnum;
import com.acooly.module.openapi.client.provider.wsbank.message.WsbankNotifyResponse;
import com.acooly.module.openapi.client.provider.wsbank.message.base.WsbankHeadResponse;
import com.acooly.module.openapi.client.provider.wsbank.message.base.WsbankResponseInfo;
import com.acooly.module.openapi.client.provider.wsbank.message.dto.WsbankNotifyResponseBody;
import com.acooly.module.openapi.client.provider.wsbank.message.dto.WsbankNotifyResponseInfo;
import com.acooly.module.openapi.client.provider.wsbank.utils.XmlUtils;
import com.acooly.module.safety.key.KeyLoadManager;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.Date;
import java.util.Map;

/**
 * @author zhike
 */
@Service
@Slf4j
public class WsbankNotifyUnmarshall extends WsbankMarshallSupport
        implements ApiUnmarshal<WsbankNotify, Map<String, String>> {
    @Resource(name = "wsbankMessageFactory")
    private MessageFactory messageFactory;

    @Autowired
    private KeyLoadManager keyStoreLoadManager;

    @SuppressWarnings("unchecked")
    @Override
    public WsbankNotify unmarshal(Map<String, String> notifyMessage, String serviceName) {
        try {
            log.info("异步通知业务参数{}", notifyMessage.get(WsbankConstants.NOTIFY_DATA_KEY));
            String signature = notifyMessage.get(WsbankConstants.NOTIFY_DATA_KEY);
            doVerifySign(signature);
            log.info("验签成功");
            return doUnmarshall(notifyMessage, serviceName);
        } catch (Exception e) {
            throw new ApiClientException("异步通知 解析失败:" + e.getMessage());
        }

    }

    protected WsbankNotify doUnmarshall(Map<String, String> message, String serviceName) {
        String notifyXml = message.get(WsbankConstants.NOTIFY_DATA_KEY);
        WsbankNotify notify = (WsbankNotify) messageFactory.getNotify(serviceName);
        notify = XmlUtils.toBean(notifyXml,notify.getClass());
        notify.setService(WsbankServiceEnum.find(serviceName).getCode());
        //组装异步响应
        WsbankNotifyResponse wsbankNotifyResponse = new WsbankNotifyResponse();
        WsbankNotifyResponseInfo notifyResponseInfo = new WsbankNotifyResponseInfo();
        WsbankHeadResponse headResponse = new WsbankHeadResponse();
        headResponse.setAppid(getProperties().getAppid());
        headResponse.setFunction(WsbankServiceEnum.find(serviceName).getKey());
        headResponse.setInputCharset("UTC+8");
        headResponse.setRespTime(Dates.format(new Date(),"yyyyMMddHHmmss"));
        headResponse.setSignType("RSA");
        headResponse.setVersion("1.0.0");
        headResponse.setReqMsgId(Ids.oid());
        notifyResponseInfo.setHeadResponse(headResponse);
        WsbankNotifyResponseBody notifyResponseBody = new WsbankNotifyResponseBody();
        WsbankResponseInfo responseInfo = new WsbankResponseInfo();
        responseInfo.setResultStatus("S");
        responseInfo.setResultCode("0000");
        responseInfo.setResultMsg("成功");
        notifyResponseBody.setResponseInfo(responseInfo);
        notifyResponseInfo.setResponseBody(notifyResponseBody);
        wsbankNotifyResponse.setResponseInfo(notifyResponseInfo);
        doVerifyParam(wsbankNotifyResponse);
        String signXml = XmlUtils.trimXml(XmlUtils.toXml(wsbankNotifyResponse));
        String notifyResponseXml = doSign(signXml,WsbankSignTypeEnum.notify_sign);
        message.put(WsbankConstants.NOTIFY_RESPONSE_DATA_KEY,notifyResponseXml);
        log.info("异步回执消息：{}",notifyResponseXml);
        return notify;
    }

    public void setMessageFactory(MessageFactory messageFactory) {
        this.messageFactory = messageFactory;
    }

}
